﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodePlex.KeyedList
{



	/// <summary>
	/// Provides a class for a collection whose keys are embedded in the values.
	/// - the key consist of two values combined
	/// </summary>
	/// <typeparam name="TKey1">The type of the first key value</typeparam>
	/// <typeparam name="TKey2">The type of the second key value</typeparam>
	/// <typeparam name="TItem">The type of items in the collection.</typeparam>
	public class KeyedList<TKey1, TKey2, TItem> : KeyedList<Key<TKey1, TKey2>, TItem>
	{

		#region Ctor


		/// <summary>
		/// Returns a new instance of the KeyedList Class, 
		/// allowing you to specify the way the TKey keys are retrived from the TItem items
		/// </summary>
		public KeyedList()
			: base()
		{
		}



		/// <summary>
		/// Returns a new instance of the KeyedList Class, 
		/// allowing you to specify the way the TKey keys are retrived from the TItem items
		/// </summary>
		/// <param name="keyForItemDelegate">the delegate that will retrive key values</param>
		public KeyedList(GetKeyForItemDelegate<Key<TKey1, TKey2>, TItem> keyForItemDelegate)
			: base(Key<TKey1, TKey2>.Comparer, keyForItemDelegate)
		{
		}

		#endregion

		/// <summary>
		/// Gets the element with the specified key values.
		/// </summary>
		/// <param name="key1"></param>
		/// <param name="key2"></param>
		/// <returns></returns>
		public virtual TItem this[TKey1 key1, TKey2 key2]
		{
			get { return base[new Key<TKey1, TKey2>(key1, key2)]; }
		}

		/// <summary>
		/// Determines whether the collection contains an element with the specified key values.
		/// </summary>
		/// <param name="key1"></param>
		/// <param name="key2"></param>
		/// <returns></returns>
		public bool Contains(TKey1 key1, TKey2 key2)
		{
			return this.Contains(new Key<TKey1, TKey2>(key1, key2));
		}

		/// <summary>
		/// Removes the element with the specified key from this Collection
		/// </summary>
		/// <param name="key1"></param>
		/// <param name="key2"></param>
		public bool Remove(TKey1 key1, TKey2 key2)
		{
			return this.Remove(new Key<TKey1, TKey2>(key1, key2));
		}


		/// <summary>
		/// Asks for and retrives a value in one operation
		/// </summary>
		/// <param name="key1"></param>
		/// <param name="key2"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public bool TryGetValue(TKey1 key1, TKey2 key2, out TItem value)
		{
			Key<TKey1, TKey2> key = new Key<TKey1, TKey2>(key1, key2);

			if(this.Contains(key))
			{
				value = this[key];
				return true;
			}

			value = default(TItem);
			return false;
		}
	}
}
